#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <cmath>
using namespace std;

class Data{
public:
    Data(){ }
    ~Data(){
        cout << "~Data" << endl;
    }

    int getData() const{
        return _data;
    }
    void print(){
        cout << "_data=" <<_data << endl;
    }
private:
    int _data = 10;
};

// 两层结构包装下的使用
class MiddLayer{
public:
    MiddLayer(Data *p)
    :_pdata(p)
    {  }
    ~MiddLayer(){
        cout << "~MiddLayer" <<endl;
        if(_pdata){
            delete _pdata;
            _pdata = nullptr;
        }
    }
    // 重装 ->  
    // 因为单->的使用对象是指针，所以要返回一个指针
    Data * operator->(){
        return _pdata;
    }
    // 重装 *
    // 因为*的使用是一个对象的解引用，返回值是一个对象
    Data & operator*(){
        return *_pdata;
    }
private:
    Data * _pdata;
};

// 引入一个三层结构ThirdLayer
// 这个类对象要包括MiddleLayer类
class ThirdLayer{
public:
    ThirdLayer(MiddLayer *ml)
    :_ml(ml)
    {   }
    
    ~ThirdLayer(){
        cout << "~ThirdLayer" << endl;
        if(_ml){
            delete _ml;
            _ml = nullptr;
        } 
    }
    // 重载 -> 
    MiddLayer & operator->(){
        // *_ml   _ml解引用之后得到的是data指针对象
        // 所以可以用&接收
        return *_ml;
    }

    // 重载 * 
    //MiddLayer & operator*(){
        // 理由同上
    //    return *_ml;
    //}

    // 像是智能指针的使用
    Data & operator*(){
        return *(*_ml);
    }

private:
    MiddLayer * _ml;
};

void test(){
    Data * p = new Data();
    MiddLayer ml(p);
    int value = p->getData();
    cout << value << endl;
    cout << "-----------" << endl;
    cout << (*p).getData() << endl;
}

void test2(){
    // MiddLayer 对象要在堆上申请，第三层不能复制在栈上的MiddleLayer
    ThirdLayer t(new MiddLayer(new Data()));
    t->print();
    cout << "---========---" << endl;
    //(*(*t)).print();
    // 要实现下面的语句调用，需要使用智能指针
    (*t).print();
}

int main(int atgc, char * argv[])
{
    test2();
    return 0;
}

